package net.cityside.dp.rp;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.print.PrinterException;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import net.cityside.dp.tools.file.FileUtils;

import org.apache.log4j.Logger;
import org.apache.tapestry5.json.JSONArray;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

public class PrintConsole extends JPanel {

	private static final long serialVersionUID = 1L;

	private static final Logger logger = Logger.getLogger(PrintConsole.class);

	private static final String VM_ENCODING = "utf-8";

	private JFileChooser fileChooser;
	private JTextField vmPathField;
	private JButton loadButton, previewButton, printButton;
	private JTextArea vmArea, dataArea;
	private JEditorPane previewArea;

	private File templateFile = null;

	private RichTextPrinter printer;

	/** 格式好的输出 */
	private String output;

	public PrintConsole() {
		createUI();

		previewButton.setEnabled(false);
		printButton.setEnabled(false);

		createEventHandlers();

		printer = new RichTextPrinter();
	}

	private void createUI() {

		BoxLayout layout = new BoxLayout(this, BoxLayout.PAGE_AXIS);
		setLayout(layout);

		fileChooser = new JFileChooser(System.getProperty("user.dir"));

		vmPathField = new JTextField(15);
		vmPathField.setEditable(false);

		loadButton = new JButton("select template");
		previewButton = new JButton("preview");
		printButton = new JButton("print");

		JPanel funtionPanel = new JPanel();
		funtionPanel.add(vmPathField);
		funtionPanel.add(loadButton);
		funtionPanel.add(previewButton);
		funtionPanel.add(printButton);
		add(funtionPanel);

		vmArea = new JTextArea(12, 60);
		add(surroundTitledPanel(new JScrollPane(vmArea), "Template"));

		dataArea = new JTextArea(3, 60);
		add(surroundTitledPanel(new JScrollPane(dataArea), "Date"));

		previewArea = new JEditorPane();
		previewArea.setContentType("text/html");
		previewArea.setPreferredSize(new Dimension(600, 200));
		previewArea.setEditable(false);
		add(surroundTitledPanel(new JScrollPane(previewArea), "Preview"));
	}

	private JComponent surroundTitledPanel(JComponent component, String title) {
		component.setBorder(BorderFactory.createTitledBorder(title));
		return component;
	}

	private void createEventHandlers() {
		loadButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {

				if (JFileChooser.APPROVE_OPTION == fileChooser
						.showOpenDialog(PrintConsole.this)) {
					templateFile = fileChooser.getSelectedFile();
					vmPathField.setText(templateFile.getAbsolutePath());
					logger.debug(templateFile.getAbsolutePath());

					try {
						vmArea.setText(FileUtils.loadFileAsString(templateFile));
					} catch (IOException ex) {
						logger.error("读取模板文件出错", ex);

						previewButton.setEnabled(false);
						printButton.setEnabled(false);

						showError("读取模板文件出错");
					}

					previewButton.setEnabled(true);
					printButton.setEnabled(true);
				}

			}
		});

		previewButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// 数据
				JSONArray jarray = new JSONArray(dataArea.getText());
				List<Tally> list = new ArrayList<Tally>();
				for (int i = 0; i < jarray.length(); i++) {
					Tally tally = new Tally(jarray.getJSONObject(i).getString(
							"name"), jarray.getJSONObject(i).getString(
							"message"));
					list.add(tally);
				}

				List<CheckRecord> checkRecs = new ArrayList<CheckRecord>();
				CheckRecord rec = new CheckRecord();
				rec.setNo(1);
				rec.setType("type1");
				rec.setDetail("玻璃门窗");
				rec.setStandard("窗明几净");
				rec.setTotal(100);
				rec.setDiff(10);
				rec.setRemark("这是一个长的 gkejgka k");
				checkRecs.add(rec);

				rec = new CheckRecord();
				rec.setNo(2);
				rec.setType("type2");
				rec.setDetail("员工都在笑");
				rec.setStandard("要笑的很傻很傻很傻很傻很傻才行");
				rec.setTotal(100);
				rec.setDiff(0);
				rec.setRemark("这是一个非常长的 gkejgka gjgkeg ewgjwkg jwk gjewgkj ew k");
				checkRecs.add(rec);

				rec = new CheckRecord();
				rec.setNo(2);
				rec.setType("type2");
				rec.setDetail("员工都很听话");
				rec.setStandard("一定要非常听哦");
				rec.setTotal(100);
				rec.setDiff(5);
				rec.setRemark("这一点做的还可以！");
				checkRecs.add(rec);

				// 加载模板
				Template template = null;
				try {
					template = Velocity.getTemplate(
							"template/" + templateFile.getName(), VM_ENCODING);
				} catch (RuntimeException ex) {
					logger.error("创建、解析模板出错", ex);
					showError("程序出错！");
					return;
				}

				// 生成、输出
				Writer writer = null;
				try {
					ByteArrayOutputStream byteStream = new ByteArrayOutputStream(
							(int) (templateFile.length() * 1.5));
					writer = new PrintWriter(byteStream);
					VelocityContext context = new VelocityContext();
					context.put("list", list);
					context.put("checks", checkRecs);
					template.merge(context, writer);
					writer.flush();
					output = byteStream.toString(VM_ENCODING);
					logger.debug(output);
					previewArea.setText(output);
				} catch (Exception ex) {
					logger.error("合并、输出时出错", ex);
					showError("程序出错！");
					return;
				} finally {
					if (writer != null) {
						try {
							writer.close();
						} catch (IOException ignored) {
						}
					}
				}
			}
		});

		printButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				logger.debug(output);
				try {
					printer.printAndWait(output);
				} catch (PrinterException ex) {
					logger.error("打印失败", ex);
					showError("打印失败" + ex.getMessage());
				}
			}
		});
	}

	private void showError(String message) {
		JOptionPane.showMessageDialog(this, message, "",
				JOptionPane.ERROR_MESSAGE);
	}
}
